package com.cq.hd.order.service.impl;

import com.cq.hd.common.enums.biz.*;
import com.cq.hd.common.response.Throw;
import com.cq.hd.common.utils.GenerateUtil;
import com.cq.hd.common.utils.LocalDateUtil;
import com.cq.hd.common.utils.NoUtils;
import com.cq.hd.member.api.TbAppUserApi;
import com.cq.hd.member.api.TbBusinessApi;
import com.cq.hd.member.api.TbBusinessMerchantApi;
import com.cq.hd.member.api.TbMerchantApi;
import com.cq.hd.member.api.dto.AutoWithdrawalRecordDto;
import com.cq.hd.member.api.dto.MerchantAmtAddDto;
import com.cq.hd.member.api.dto.MerchantAmtBillSaveDto;
import com.cq.hd.member.api.dto.OrderSettleUpdateDto;
import com.cq.hd.member.api.vo.BusinessMerchantVo;
import com.cq.hd.member.api.vo.BusinessPageVo;
import com.cq.hd.member.api.vo.MerchantVo;
import com.cq.hd.order.mapper.TbOrderMapper;
import com.cq.hd.order.mapper.TbOrderSettleBillMapper;
import com.cq.hd.order.mapper.TbOrderUnverifiedRecordMapper;
import com.cq.hd.order.po.TbOrderPo;
import com.cq.hd.order.po.TbOrderSettleBillPo;
import com.cq.hd.order.po.TbOrderUnverifiedRecordPo;
import com.cq.hd.order.service.TbOrderUnverifiedRecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @author much
 * @since 2024/09/30 20:31
 */
@Slf4j
@Service
public class TbOrderUnverifiedRecordServiceImpl implements TbOrderUnverifiedRecordService {

    @Resource
    private TbOrderUnverifiedRecordMapper orderUnverifiedRecordMapper;
    @Resource
    private TbOrderMapper orderMapper;
    @Resource
    private TbOrderSettleBillMapper orderSettleBillMapper;
    @Resource
    private TbBusinessApi businessApi;
    @Resource
    private TbBusinessMerchantApi businessMerchantApi;
    @Resource
    private TbMerchantApi merchantApi;
    @Resource
    private TbAppUserApi appUserApi;
    @Resource
    private PlatformTransactionManager transactionManager;

    @Override
    public void addOrderUnverifiedRecord(TbOrderUnverifiedRecordPo record) {
        record.setState(0);
        LocalDateTime now = LocalDateTime.now();
        record.setCreateTime(now);
        record.setUpdateTime(now);
        orderUnverifiedRecordMapper.insert(record);
    }

    @Override
    public void scanPendingRecords() {
        List<TbOrderUnverifiedRecordPo> pendingRecords = orderUnverifiedRecordMapper.selectPendingRecords();
        if (CollectionUtils.isEmpty(pendingRecords)) {
            return;
        }
        for (TbOrderUnverifiedRecordPo record : pendingRecords) {
            processPendingRecord(record);
        }
    }

    private void processPendingRecord(TbOrderUnverifiedRecordPo record) {
        if (record.getState() == 1) {
            log.error("processPendingRecord: orderId: {} record state is not 0, state: {}", record.getOrderId(), record.getState());
            return;
        }

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());
        try {
            TbOrderSettleBillPo orderSettleBillPo = addOrderSettleBill(record);
            // 更新状态为已处理
            record.setState(1);
            record.setOrderSettleBillId(orderSettleBillPo.getId());
            record.setUpdateTime(LocalDateTime.now());
            orderUnverifiedRecordMapper.updateById(record);
            // 更新商户账户余额和记录明细
            updateMerchantAccountAmt(orderSettleBillPo);

            transactionManager.commit(transaction);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            transactionManager.rollback(transaction);
        }
    }

    // 更新商户账户余额和资金明细
    private void updateMerchantAccountAmt(TbOrderSettleBillPo orderSettleBillPo) {
        MerchantVo merchantVo = merchantApi.getById(orderSettleBillPo.getMerchantId()).unpack();
        BigDecimal beforeBalanceAmt = merchantVo.getBalanceAmt();
        BigDecimal afterMerchantAmt = beforeBalanceAmt.add(orderSettleBillPo.getTradeAmt());
        MerchantAmtAddDto merchantAmtAddDto = new MerchantAmtAddDto();
        merchantAmtAddDto.setId(orderSettleBillPo.getMerchantId());
        merchantAmtAddDto.setBalanceAmt(orderSettleBillPo.getTradeAmt());
        merchantAmtAddDto.setSubsidyAmt(BigDecimal.ZERO);

        TbOrderPo tbOrderPo = orderMapper.selectById(orderSettleBillPo.getOrderId());
        MerchantAmtBillSaveDto merchantAmtBillSaveDto = new MerchantAmtBillSaveDto();
        merchantAmtBillSaveDto.setOrderId(orderSettleBillPo.getOrderId());
        merchantAmtBillSaveDto.setBillNo(NoUtils.getMemberAmtBillNo());
        merchantAmtBillSaveDto.setMerchantId(orderSettleBillPo.getMerchantId());
        merchantAmtBillSaveDto.setBillType(BillTypeEnum.INCOME.getValue());
        merchantAmtBillSaveDto.setTradeType(MemberAmtBillTradeTypeEnum.ORDER_INCOME_AMT.getValue());
        merchantAmtBillSaveDto.setRelationTradeNo(tbOrderPo.getOrderNo());
        merchantAmtBillSaveDto.setBeforeAmt(beforeBalanceAmt);
        merchantAmtBillSaveDto.setTradeAmt(orderSettleBillPo.getTradeAmt());
        merchantAmtBillSaveDto.setAfterAmt(afterMerchantAmt);
        LocalDateTime now = LocalDateTime.now();
        merchantAmtBillSaveDto.setTradeTime(now);
        merchantAmtBillSaveDto.setCreateTime(now);
        merchantAmtBillSaveDto.setUpdateTime(now);

        // 自动提现记录
        AutoWithdrawalRecordDto autoWithdrawalRecordDto = new AutoWithdrawalRecordDto();
        autoWithdrawalRecordDto.setBillId(orderSettleBillPo.getId());
        autoWithdrawalRecordDto.setOrderId(orderSettleBillPo.getOrderId());
        autoWithdrawalRecordDto.setBusinessId(orderSettleBillPo.getBusinessId());
        autoWithdrawalRecordDto.setMerchantId(orderSettleBillPo.getMerchantId());
        autoWithdrawalRecordDto.setWithdrawalAmt(orderSettleBillPo.getTradeAmt());
        autoWithdrawalRecordDto.setState(AutoWithdrawalStateEnum.WAIT.getValue());

        // 3、更新商户本金，商户补贴和经纪人佣金，添加商户资金流水和经纪人佣金流水，统计商家与经纪人的累计结算分销佣金
        OrderSettleUpdateDto orderSettleUpdateDto = new OrderSettleUpdateDto();
        orderSettleUpdateDto.setOrderId(orderSettleUpdateDto.getOrderId());
        orderSettleUpdateDto.setMerchantAmtAdds(Collections.singletonList(merchantAmtAddDto));
        orderSettleUpdateDto.setMerchantAmtBillSaves(Collections.singletonList(merchantAmtBillSaveDto));
        // 普通商户的本金需要自动提现
        orderSettleUpdateDto.setAutoWithdrawalRecords(Collections.singletonList(autoWithdrawalRecordDto));
        Boolean updateOrderSettleAmtState = appUserApi.updateOrderSettleAmt(orderSettleUpdateDto).unpack();
        if (updateOrderSettleAmtState == null || !updateOrderSettleAmtState) {
            log.error("更新商户账户余额和资金明细，orderSettleBillId：{}", orderSettleBillPo.getId());
            Throw.isBusinessException("更新商户账户余额和资金明细");
        }
    }

    private TbOrderSettleBillPo addOrderSettleBill(TbOrderUnverifiedRecordPo record) {
        TbOrderPo order = orderMapper.selectById(record.getOrderId());
        TbOrderSettleBillPo orderSettleBill = new TbOrderSettleBillPo();
        // 商家信息
        BusinessPageVo businessVo = businessApi.getById(order.getBusinessId()).unpack();
        // 商家自有商户信息
        BusinessMerchantVo businessMerchantVo = businessMerchantApi.getOwnByBusinessId(
                order.getBusinessId(), OwnStateEnum.YES.getValue()).unpack();

        orderSettleBill.setOrderId(order.getId());
        orderSettleBill.setActiveId(order.getActiveId());
        orderSettleBill.setBusinessId(order.getBusinessId());
        orderSettleBill.setMerchantId(businessMerchantVo.getMerchantId());
        orderSettleBill.setUserId(order.getUserId());
        orderSettleBill.setTradeType(OrderSettleBillTradeTypeEnum.RECOVER_AMT.getValue());
        orderSettleBill.setTradeAmt(record.getRecoverAmt());
        orderSettleBill.setReceiveAmt(record.getRecoverAmt());
        orderSettleBill.setFeeAmt(BigDecimal.ZERO);
        orderSettleBill.setInHfId(businessVo.getHfMerchantNo());
        orderSettleBill.setInHfAcctId(businessVo.getHfAcctId());

        LocalDateTime nowLocalDateTime = LocalDateUtil.getNowLocalDateTime();
        String yyyyMMdd = LocalDateUtil.toLocalDateToString(nowLocalDateTime.toLocalDate(), "yyyyMMdd");
        String reqSeqId = LocalDateUtil.toLocalDateTimeToString(nowLocalDateTime, "yyyyMMddHHmmss") + GenerateUtil.getRandomNum(5);
        orderSettleBill.setReqDate(yyyyMMdd);
        orderSettleBill.setReqSeqId(reqSeqId);
        orderSettleBill.setTradeTime(nowLocalDateTime);
        orderSettleBill.setCreateTime(nowLocalDateTime);
        orderSettleBill.setUpdateTime(nowLocalDateTime);
        orderSettleBill.setTradeState(OrderSettleBillTradeStateEnum.WAIT.getValue());

        orderSettleBillMapper.insert(orderSettleBill);

        return orderSettleBill;
    }


}
